package com.wecon.springdemo.jwt.impl;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.wecon.springdemo.jwt.config.JwtProperties;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @description: 自定义的JWT token管理
 * @author: Weikang Wang
 * @date: 2021/3/15 17:04
 */
@Service("jwtTokenManager")
@EnableConfigurationProperties(JwtProperties.class)
@Slf4j
public class JwtTokenManager {

    @Resource
    JwtProperties jwtProperties;

    /**
     * @param: iss 签发者
     * @param: ttlMillis 过期时间
     * @param: sessionId sessionID
     * @param: claims 存储的费隐私信息
     * @description: 签发令牌
     * @return: java.lang.String
     * @author: Weikang Wang
     * @date: 2021/3/15 18:12
     */
    public String issusedToken(String iss, long ttlMillis, String sessionId, Map<String, Object> claims) {
        log.info("jwt签发令牌操作，iss:{}, ttlMillis:{}, sessionId:{}, claims:{}", iss, ttlMillis, sessionId, claims);

        if (claims.isEmpty()) {
            claims = new HashMap<>();
        }

        // 获取当前时间
        long millis = System.currentTimeMillis();
        // 获取加密签名
        // TODO 加密算法
        String jwtSecretKey = jwtProperties.getJwtSecretKey();
        // 构建令牌
        JwtBuilder jwtBuilder = Jwts.builder()
                .setClaims(claims)
                .setId(sessionId)
                .setIssuedAt(new Date(millis))
                .setSubject(iss)
                .signWith(SignatureAlgorithm.HS256, jwtSecretKey);

        // 指定过期时间
        if (ttlMillis > 0) {
            long expMil = millis + ttlMillis;
            jwtBuilder.setExpiration(new Date(expMil));
        }

        return jwtBuilder.compact();
    }

    /**
     * @param: jwtToken
     * @description: 解析令牌
     * @return: io.jsonwebtoken.Claims
     * @author: Weikang Wang
     * @date: 2021/3/15 19:21
     */
    public Claims decodeToken(String jwtToken) {
        log.info("解析jwt操作");

        // 获取加密签名
        String jwtSecretKey = jwtProperties.getJwtSecretKey();
        // 带着密码解析字符串
        return Jwts.parser()
                .setSigningKey(jwtSecretKey)
                .parseClaimsJws(jwtToken)
                .getBody();
    }

    /**
     * @param: jwtToken
     * @description: 校验令牌：1.头部信息header和载荷payload是否被篡改；2.校验令牌是否过期
     * @return: boolean
     * @author: Weikang Wang
     * @date: 2021/3/15 19:26
     */
    public boolean isVerifyToken(String jwtToken) {
        log.info("校验jwt令牌操作");

        // 获取加密签名
        String jwtSecretKey = jwtProperties.getJwtSecretKey();

        // 带着签名构建校验对象
        Algorithm algorithm = Algorithm.HMAC256(jwtSecretKey);
        JWTVerifier jwtVerifier = JWT.require(algorithm).build();

        // 校验：如果校验不通过则会抛出JWTVerificationException异常
        jwtVerifier.verify(jwtToken);
        return true;
    }

}
